<template>
  <div :id="demo.demoId" class="b-a br-sm" :class="currDemoId == demo.demoId ? 'b-a-success' : ''">
    <div class="px24 py20">
      <!-- DEMO 的标题 + 说明desc+  示例wcTag -->
      <div class="f-r f-pos-between f-box-end pb20">
        <div class="f18 cur-hand">{{ demo.name[langKey] }}</div>
        <div>
          <n-tooltip trigger="hover">
            <template #trigger>
              <i :class="copyIcon" class="h:c-success w16 h16 cur-hand" @click="copyCode(demo)" @mouseout="resetTip()" />
            </template>
            {{ copyTip }}
          </n-tooltip>
          <n-tooltip trigger="hover">
            <template #trigger>
              <i :class="!!demo.isOpen ? 'i-ti-codeslash' : 'i-ti-code'" class="ml8 h:c-success w16 h16 cur-hand" @click="toggleDemoCode(demo)" />
            </template>
            {{ demo.isOpen ? $t('hideCode') : $t('showCode') }}
          </n-tooltip>
        </div>
      </div>
      <div v-if="descMd" v-html="descMd" class="markdown-body"></div>
      <component v-else :is="getDescMd(demo)" class="mb16 f14" />
      <div v-if="demoConfig.isMobile" class="phone-container">
        <div class="mobile-view-container">
          <component :is="vueComponents[`${cmpId}/${demo.codeFiles[0]}`]" />
        </div>
      </div>
      <component v-else :is="vueComponents[`${cmpId}/${demo.codeFiles[0]}`]" />
    </div>
    <!-- demo 打开后的示例代码  细滚动时，width:fit-content; -->
    <div v-if="demo.isOpen" class="px24 py20 b-t-lightless">
      <n-config-provider :theme-overrides="themeOverrides">
        <n-tabs v-model:value="tabValue" type="line" size="large" justify-content="space-evenly" @update:value="handleUpdateValue(demo)">
          <n-tab-pane v-for="(file, idx) in demo.files" :key="file.fileName" :name="'tab' + idx" :tab="file.fileName">
            <n-layout :native-scrollbar="true" :content-style="`overflow-x:auto; padding: 20px 5px; background-color:#f5f6f8;`">
              <n-code :code="file.code" :language="file.language" />
            </n-layout>
          </n-tab-pane>
        </n-tabs>
      </n-config-provider>
    </div>
  </div>
</template>
<script lang="jsx">
import { defineComponent, reactive, computed, toRefs, onMounted } from 'vue';
import { $t, $t2 } from '@/i18n';
import { $split, appData, fetchDemosFile } from '@/tools';
import { languageMap, themeOverrides, vueComponents } from './cmpConfig';
import { router } from '@/router.js';
import demoConfig from '@demos/config.js';

const getDemoCodeFn = demo => {
  // 获取code代码文本
  if (!demo.files) {
    const cmpId = router.currentRoute.value.params.cmpId;
    demo.files = demo.codeFiles.map(fileName => {
      const ext = $split(fileName, '.', -1);
      const language = languageMap[ext] || '';

      return { fileName, language, files: [] };
    });
  }
};

export default defineComponent({
  name: 'Demo',
  props: ['demo'],
  setup(props) {
    const state = reactive({
      tabValue: 'tab0',
      cmpId: router.currentRoute.value.params.cmpId,
      langKey: $t2('zh-CN', 'en-US'),
      currDemoId: computed(() => {
        let hash = router.currentRoute.value.hash?.slice(1);

        // 兼容/#hashName这种模式
        if (hash.indexOf('/') > -1) {
          hash = hash.slice(1);
        }
        return hash;
      }),
      copyTip: $t('copyCode'),
      copyIcon: 'i-ti-copy',
      themeOverrides: themeOverrides,
      descMd: null,
    });
    const fn = {
      getDescMd(demo) {
        // desc字段可能是md,也可能是html。 返回md组件或者html组件
        const desc = demo.desc[state.langKey].trim();
        return <div class="demo-desc" v-html={desc}></div>;
      },
      toggleDemoCode(demo) {
        // 第一次打开时，要请求一下相应的codeFiles .存储到files属性下
        if (!demo.files) {
          this.getDemoCode(demo);
          demo.isOpen = true;
        } else {
          demo.isOpen = !demo.isOpen;
        }
      },
      async copyCode(demo) {
        const idx = demo.isOpen ? parseInt(state.tabValue.slice(3)) : 0;
        if (!demo.files) {
          const code = await this.getDemoCode(demo);
        }
        navigator.clipboard.writeText(demo.files[idx].code);
        state.copyTip = $t('copyCodeOk');
        state.copyIcon = 'i-ti-check';
      },
      resetTip() {
        setTimeout(() => {
          state.copyTip = $t('copyCode');
          state.copyIcon = 'i-ti-copy';
        }, 300);
      },
      handleUpdateValue(demo) {
        const idx = parseInt(state.tabValue.slice(3));

        if (!demo.files[idx].code) {
          const path = `@demos/app/${state.cmpId}/${demo.files[idx].fileName}`;
          fetchDemosFile(path)
            .then(code => {
              demo.files[idx].code = code;
            })
            .catch(error => {});
        }
      },
      async getDemoCode(demo) {
        await getDemoCodeFn(demo);
        // 获取code代码文本
        const idx = demo.isOpen ? parseInt(state.tabValue.slice(3)) : 0;
        const path = `@demos/app/${state.cmpId}/${demo.files[idx].fileName}`;
        const code = await fetchDemosFile(path);
        state.demo.files[idx].code = code;
        return code;
      },
    };
    onMounted(() => {
      getDemoCodeFn(props.demo);
    });
    return { ...toRefs(state), ...fn, appData, vueComponents, demoConfig };
  },
});
</script>
<style lang="less">
.demo-desc {
  line-height: 1.5;
  code {
    background: #f1f2f3;
    padding: 2px 4px;
    border-radius: 2px;
    margin: 2px 4px;
    display: inline-block;
  }

  a {
    text-decoration: none;
    color: #5e7ce0;
    cursor: pointer;
  }
}

.theme-dark {
  .demo-desc {
    code {
      background: #333333;
    }
  }
}

.b-a-success {
  animation: border-trans 3s;
}
@keyframes border-trans {
  0% {
    border: 1px solid #5073e5;
    background: none;
  }
  50% {
    background: rgba(255, 95, 85, 0.1);
    border: 1px solid rgba(255, 95, 88, 0.6);
  }
  100% {
    border: 1px solid #5073e5;
    background: none;
  }
}
.phone-container {
  margin: auto;
  width: 395px;
  height: 773px;
  padding: 20px;
  border: 0;
  position: relative;
  background: url()
    no-repeat center top;
  background-size: contain;

  .mobile-view-container {
    width: 360px;
    height: 613px;
    position: absolute;
    left: 11px;
    top: 79px;
    transform: translateX(0);
    overflow: hidden;
  }
}
</style>
